package com.corpgovernment.contract.service.impl;


import com.corpgovernment.api.messageadvice.vo.EmailInfo;
import com.corpgovernment.common.apollo.OrganizationApollo;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.enums.ExceptionCodeEnum;
import com.corpgovernment.common.utils.DateUtil;
import com.corpgovernment.contract.entity.MbContractInfo;
import com.corpgovernment.contract.mapper.ContractInfoMapper;
import com.corpgovernment.contract.service.ContractInfoService;
import com.corpgovernment.contract.vo.ContractInfoPage;
import com.corpgovernment.contract.vo.ContractInfoVo;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.entity.db.MbOrgEmployeeInfo;
import com.corpgovernment.organization.entity.db.MbOrgInfo;
import com.corpgovernment.organization.mq.SendEmailMQProducer;
import com.corpgovernment.organization.service.IOrganizationEmployeeService;
import com.corpgovernment.organization.service.IOrganizationInfoService;
import com.corpgovernment.supplier.entity.db.MbSupplierInfo;
import com.corpgovernment.supplier.service.MbSupplierInfoService;
import com.ctrip.corp.obt.generic.core.context.RequestContext;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.corpgovernment.permission.config.PermissionFilter.DATA_PERMISSION_ORG_ID_LIST;

@Service
@Slf4j
public class ContractInfoServiceImpl implements ContractInfoService {

    @Autowired
    private ContractInfoMapper contractInfoMapper;
    @Autowired
    private IOrganizationInfoService organizationInfoService;
    @Autowired
    private OrganizationApollo organizationApollo;
    @Autowired
    private SendEmailMQProducer sendEmailMQProducer;
    @Autowired
    private IOrganizationEmployeeService organizationEmployeeService;
    @Autowired
    private MbSupplierInfoService supplierInfoService;
    /**
     * 未生效
     */
    private final static Integer valid_status_1 = 1;
    /**
     * 已生效
     */
    private final static Integer valid_status_2 = 2;
    /**
     * 失效
     */
    private final static Integer valid_status_3 = 3;

    /**
     * 未发送
     */
    private final static Integer send_status_1 = 1;
    /**
     * 已发送
     */
    private final static Integer send_status_2 = 2;

    public void check(ContractInfoVo request){
        if (StringUtils.isNotBlank(request.getRemark()) && request.getRemark().length() > 50){
            throw new CorpBusinessException(OrganizationResponseCodeEnum.CONTRACT_REMARK_LIMIT_LENGTH);
        }
        if (StringUtils.isBlank(request.getContractName())){
            throw new CorpBusinessException(OrganizationResponseCodeEnum.CONTRACT_NAME_IS_NULL);
        }
        if (Objects.isNull(request.getValidStatus())){
            throw new CorpBusinessException(OrganizationResponseCodeEnum.CONTRACT_STATUS_IS_NULL);
        }
        if (StringUtils.isNotBlank(request.getEmail())){
            boolean matches = Pattern.matches("^(\\w+([-.][A-Za-z0-9]+)*){3,18}@\\w+([-.][A-Za-z0-9]+)*\\.\\w+([-.][A-Za-z0-9]+)*$", request.getEmail());
            if (!matches){
                throw new CorpBusinessException(OrganizationResponseCodeEnum.CONTRACT_EMAIL_FORMAT_ERROR);
            }
        }
    }

    @Override
    public boolean save(ContractInfoVo request) {
        check(request);
        MbContractInfo mbContractInfo = new MbContractInfo();
        mbContractInfo.setContractCode(request.getContractCode());
        mbContractInfo.setContractName(request.getContractName());
        mbContractInfo.setContractType(request.getContractType());
        mbContractInfo.setContractStartDate(DateUtil.stringToDate(request.getContractStartDate(), DateUtil.DF_YMD));
        mbContractInfo.setContractEndDate(DateUtil.stringToDate(request.getContractEndDate(), DateUtil.DF_YMD));
        mbContractInfo.setSupplierCode(request.getSupplierCode());
        mbContractInfo.setSupplierName(request.getSupplierName());
        mbContractInfo.setOrgId(request.getOrgId());
        mbContractInfo.setAttachment(JsonUtils.toJsonString(request.getAttachments()));
        mbContractInfo.setRemark(request.getRemark());
        mbContractInfo.setValidStatus(Objects.nonNull(request.getValidStatus()) && request.getValidStatus()>0 ? request.getValidStatus() : valid_status_1);
        mbContractInfo.setSendStatus(Objects.nonNull(request.getSendStatus()) && request.getSendStatus()>0 ? request.getSendStatus() : send_status_1);
        mbContractInfo.setEmail(request.getEmail());
        if (Objects.nonNull(request.getId()) && request.getId() > 0){
            //修改
            mbContractInfo.setDatachangeLasttime(new Date());
            mbContractInfo.setId(request.getId());
            contractInfoMapper.updateByPrimaryKeySelective(mbContractInfo);
        }else {
            //新增
            mbContractInfo.setOperator(request.getUname());
            mbContractInfo.setOperatorUid(request.getUid());
            //未删除
            mbContractInfo.setIsDeleted(Boolean.FALSE);
            mbContractInfo.setDatachangeCreatetime(new Date());
            mbContractInfo.setDatachangeLasttime(new Date());
            contractInfoMapper.insert(mbContractInfo);
        }
        if (Objects.equals(request.getSendStatus(), send_status_2) && StringUtils.isNotBlank(request.getSupplierCode())){
            MbSupplierInfo mbSupplierInfo = supplierInfoService.loadBySupplierCode(request.getSupplierCode());
            if (Objects.nonNull(mbSupplierInfo) && StringUtils.isNotBlank(mbSupplierInfo.getContractEmail())){
                EmailInfo emailInfo = new EmailInfo();
                emailInfo.setSubject("合同管理发送供应商");
                emailInfo.setSender_nickName("系统邮件");
                emailInfo.setReceiveUser(mbSupplierInfo.getContractEmail());
                StringBuilder urlSb = new StringBuilder();
                String href = organizationApollo.getPortalHost() + "#/contractManager";
                String context = String.format("您有新的合同信息，请点击<a href='%s'>此处</a>及时查看合同信息，并尽快处理。\n 您可以复制以下地址并粘帖在浏览器的地址栏中访问：%s", href, href);
                emailInfo.setContent(context);
                sendEmailMQProducer.sendEmail(emailInfo);
            }
        }
        return true;
    }

    @Override
    public boolean deleteById(Long id) {
        MbContractInfo mbContractInfo = new MbContractInfo();
        mbContractInfo.setId(id);
        mbContractInfo.setValidStatus(valid_status_3);
        mbContractInfo.setIsDeleted(Boolean.TRUE);
        mbContractInfo.setDatachangeLasttime(new Date());
        contractInfoMapper.updateByPrimaryKeySelective(mbContractInfo);
        return true;
    }

    @Override
    public ContractInfoPage selectContractInfoPage(ContractInfoVo request) {
        // 数据权限获取
        List<String> accessibleOrgIdList = getAccessibleOrgIdList();

        Example example = new Example(MbContractInfo.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(request.getContractCode())){
            criteria.andLike("contractCode", '%' + request.getContractCode() + "%");
        }
        if (StringUtils.isNotBlank(request.getContractName())){
            criteria.andLike("contractName", "%" + request.getContractName() + "%");
        }
        if (StringUtils.isNotBlank(request.getRemark())){
            criteria.andLike("remark", "%" + request.getRemark() + "%");
        }
        if (Objects.nonNull(request.getContractType())){
            criteria.andEqualTo("contractType", request.getContractType());
        }
        if (StringUtils.isNotBlank(request.getCreateDate())){
            criteria.andGreaterThanOrEqualTo("datachangeCreatetime", request.getCreateDate());
        }
        if (StringUtils.isNotBlank(request.getEndDate())){
            criteria.andLessThanOrEqualTo("datachangeCreatetime", request.getEndDate());
        }
        if (StringUtils.isNotBlank(request.getOrgId())){
            if (CollectionUtils.isNotEmpty(accessibleOrgIdList) && !accessibleOrgIdList.contains(request.getOrgId())) {
                // 不在数据权限可访问范围内，返回空
                ContractInfoPage emptyInfoPage = new ContractInfoPage();
                emptyInfoPage.setList(Collections.EMPTY_LIST);
                emptyInfoPage.setCurrentPage(request.getCurrentPage());
                emptyInfoPage.setPageSize(request.getPageSize());
                emptyInfoPage.setTotalCount(0L);
                emptyInfoPage.setTotalPage(0);
                return emptyInfoPage;
            }
            criteria.andEqualTo("orgId", request.getOrgId());
        }
        if (Objects.nonNull(request.getSendStatus()) && request.getSendStatus() > 0){
            criteria.andEqualTo("sendStatus", request.getSendStatus());
        }
        if (Objects.nonNull(request.getValidStatus()) && request.getValidStatus() > 0){
            criteria.andEqualTo("validStatus", request.getValidStatus());
        }
        if (StringUtils.isNotBlank(request.getOperator())){
            criteria.andLike("operator", "%" + request.getOperator() + "%");
        }
        if (StringUtils.isNotBlank(request.getSupplierCode())){
            criteria.andEqualTo("supplierCode", request.getSupplierCode());
        }
        List<MbOrgInfo> orgInfoList = organizationInfoService.listAll();

        if (StringUtils.isNotBlank(request.getOrgName())){
            List<String> orgIds = orgInfoList.stream().filter(item -> item.getName().indexOf(request.getOrgName()) > -1).map(MbOrgInfo::getOrgId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(accessibleOrgIdList)) {
                // 仅查询数据权限可访问范围内orgId
                orgIds = orgIds.stream().filter(accessibleOrgIdList::contains).collect(Collectors.toList());
                log.info("数据权限过滤结果：orgIds:{}", JsonUtils.toJsonString(orgIds));
            }
            if (CollectionUtils.isNotEmpty(orgIds) && orgIds.size() > 0){
                criteria.andIn("orgId", orgIds);
            } else{
                criteria.andIn("orgId", Lists.newArrayList(" "));
            }
        } else if (CollectionUtils.isNotEmpty(accessibleOrgIdList)) {
            // 仅查询数据权限可访问范围内orgId
            criteria.andIn("orgId", accessibleOrgIdList);
        }

        criteria.andEqualTo("isDeleted", Boolean.FALSE);
        example.orderBy("datachangeLasttime").desc();
        PageHelper.startPage(request.getCurrentPage(), request.getPageSize());
        List<MbContractInfo> mbContractInfos = contractInfoMapper.selectByExample(example);
        log.info("合同信息：{}", JsonUtils.toJsonString(mbContractInfos));
        PageInfo<MbContractInfo> pageInfo = new PageInfo<>(mbContractInfos);
        ContractInfoPage infoPage = new ContractInfoPage();
        List<ContractInfoPage.ContractInfo> convertList = new ArrayList<>();

        Map<String, MbOrgInfo> orgInfoMap = orgInfoList.stream().collect(Collectors.toMap(MbOrgInfo::getOrgId, Function.identity(), (k1, k2) -> k2));
        for (MbContractInfo info:pageInfo.getList()){
            ContractInfoPage.ContractInfo contractInfo = new ContractInfoPage.ContractInfo();
            contractInfo.setId(info.getId());
            contractInfo.setContractCode(info.getContractCode());
            contractInfo.setContractName(info.getContractName());
            contractInfo.setContractType(info.getContractType());
            contractInfo.setContractEndDate(DateUtil.dateToString(info.getContractEndDate(), DateUtil.DF_YMD));
            contractInfo.setContractStartDate(DateUtil.dateToString(info.getContractStartDate(), DateUtil.DF_YMD));
            contractInfo.setSupplierCode(info.getSupplierCode());
            contractInfo.setSupplierName(info.getSupplierName());
            contractInfo.setRemark(info.getRemark());
            contractInfo.setIsDeleted(info.getIsDeleted());
            contractInfo.setSendStatus(info.getSendStatus());
            contractInfo.setValidStatus(info.getValidStatus());
            contractInfo.setOperator(info.getOperator());
            contractInfo.setOrgId(info.getOrgId());
            contractInfo.setCreateDate(DateUtil.dateToString(info.getDatachangeCreatetime(), DateUtil.DF_YMD_HMS));
            contractInfo.setLastUpdateDate(DateUtil.dateToString(info.getDatachangeLasttime(), DateUtil.DF_YMD_HMS));
            if (StringUtils.isNotBlank(info.getAttachment())){
                List<ContractInfoPage.Attachment> attachment = JsonUtils.parseArray(info.getAttachment(), ContractInfoPage.Attachment.class);
                contractInfo.setAttachments(attachment);
            }
            contractInfo.setOrgName(Optional.ofNullable(orgInfoMap.get(info.getOrgId())).map(MbOrgInfo::getOrgId).orElse(""));
            convertList.add(contractInfo);
        }
        log.info("合同信息分页后：{}", JsonUtils.toJsonString(convertList));
        infoPage.setList(convertList);
        infoPage.setCurrentPage(request.getCurrentPage());
        infoPage.setPageSize(request.getPageSize());
        infoPage.setTotalCount(pageInfo.getTotal());
        infoPage.setTotalPage(pageInfo.getPages());
        return infoPage;
    }

    private List<String> getAccessibleOrgIdList() {
        // 数据权限管控
        Object orgIds = RequestContext.getCurrentContext().getContextParams(DATA_PERMISSION_ORG_ID_LIST);
        List<String> listOrgIds = new ArrayList<>();
        if (Objects.nonNull(orgIds)) {
            String str = JsonUtils.toJsonString(orgIds);
            if (StringUtils.isNotBlank(str)) {
                log.info("获取到的数据权限为：{}", str);
                listOrgIds = JsonUtils.parseArray(str, String.class);
            }
        }
        return listOrgIds;
    }

    @Override
    public boolean validStatusUpdate(ContractInfoVo request) {
        MbContractInfo mbContractInfo = contractInfoMapper.selectByPrimaryKey(request.getId());
        //改为生效是判断 合同日期是否过了
        if (Objects.equals(valid_status_2, request.getValidStatus())){
            if (Objects.nonNull(mbContractInfo.getContractEndDate()) && mbContractInfo.getContractEndDate().compareTo(new Date()) < 0){
                throw new CorpBusinessException(OrganizationResponseCodeEnum.CONTRACT_VALID);
            }
        }
        MbContractInfo updateContractInfo = new MbContractInfo();
        updateContractInfo.setId(request.getId());
        updateContractInfo.setValidStatus(request.getValidStatus());
        contractInfoMapper.updateByPrimaryKeySelective(updateContractInfo);

        if (Objects.equals(valid_status_2, request.getValidStatus())){
            MbOrgEmployeeInfo employeeInfo = organizationEmployeeService.findAllByUid(mbContractInfo.getOperatorUid());
            if (StringUtils.isNotBlank(employeeInfo.getEmail())){
                EmailInfo emailInfo = new EmailInfo();
                emailInfo.setSubject("合同管理生效");
                emailInfo.setSender_nickName("系统邮件");
                emailInfo.setReceiveUser(employeeInfo.getEmail());
                StringBuilder urlSb = new StringBuilder();

                String href = organizationApollo.getPcAdminHost() + "#/contractManager";
                String context = String.format("您的%s合同已经生效，可请点击<a href='%s'>此处</a>及时查看合同信息\n 您可以复制以下地址并粘帖在浏览器的地址栏中访问：%s", mbContractInfo.getContractName(), href, href);
                emailInfo.setContent(context);
                sendEmailMQProducer.sendEmail(emailInfo);
            }
        }

        return true;
    }

    @Override
    public boolean sendStatusUpdate(ContractInfoVo request) {
        MbContractInfo updateContractInfo = new MbContractInfo();
        updateContractInfo.setId(request.getId());
        updateContractInfo.setSendStatus(request.getSendStatus());
        contractInfoMapper.updateByPrimaryKeySelective(updateContractInfo);
        return true;
    }

    @Override
    public boolean validStatusJob() {
        Example example = new Example(MbContractInfo.class);
        example.createCriteria().andLessThanOrEqualTo("contractEndDate", DateUtil.addDays(new Date(), -1));
        MbContractInfo updateContractInfo = new MbContractInfo();
        updateContractInfo.setValidStatus(valid_status_3);
        contractInfoMapper.updateByExampleSelective(updateContractInfo, example);
        return true;
    }
}
